using Common.Models;
using FileClient.Models;
using FileClient.Utils;
using System.ComponentModel;
using System.Threading.Tasks;

namespace FileClient
{
    public partial class MainForm : Form
    {
        /// <summary>
        /// 提供文件下载服务的核心组件，负责协调下载任务的执行与状态管理。
        /// </summary>
        private FileDownloadService downloadService;

        /// <summary>
        /// 存储所有待处理文件的元数据集合，包含文件大小、名称等关键信息。
        /// </summary>
        private List<FileData> fileList = new List<FileData>();

        /// <summary>
        /// 映射文件标识符到对应下载任务的字典，用于实时跟踪各任务执行状态。
        /// </summary>
        private Dictionary<string, DownloadTask> downloadTasks = new Dictionary<string, DownloadTask>();

        /// <summary>
        /// 指定所有下载文件的持久化存储路径，确保文件集中管理及权限控制。
        /// </summary>
        private string downloadDirectory;

        private const string PauseText = "暂停下载";
        private const string ResumeText = "继续下载";
        private const string StatusDownloading = "下载中";
        private const string StatusPaused = "已暂停";

        public MainForm()
        {
            InitializeComponent();
            InitializeDownloadService();
            UpdateDownloadButtonsEnabled();
        }

        private void MainForm_FormClosing(object? sender, FormClosingEventArgs e)
        {
            downloadTasks?.Clear();
            downloadService?.Dispose();
        }

        private void InitializeDownloadService()
        {
            downloadDirectory = Path.Combine(AppContext.BaseDirectory, "Downloads");
            if (!Directory.Exists(downloadDirectory))
            {
                Directory.CreateDirectory(downloadDirectory);
            }
            downloadService = new FileDownloadService(txtServerUrl.Text, downloadDirectory);
            downloadService.DownloadProgressChanged += DownloadService_DownloadProgressChanged;
            downloadService.DownloadCompleted += DownloadService_DownloadCompleted;
            downloadService.DownloadError += DownloadService_DownloadError;
        }

        private void UpdateDownloadButtonsEnabled()
        {
            bool hasItems = listViewDownloads.Items.Count > 0;
            btnPauseResume.Enabled = hasItems;
            btnCancel.Enabled = hasItems;
        }

        private async void BtnConnect_Click(object? sender, EventArgs e)
        {
            try
            {
                if (downloadService != null)
                {
                    downloadService.Dispose();
                }

                downloadService = new FileDownloadService(txtServerUrl.Text, downloadDirectory);
                downloadService.DownloadProgressChanged += DownloadService_DownloadProgressChanged;
                downloadService.DownloadCompleted += DownloadService_DownloadCompleted;
                downloadService.DownloadError += DownloadService_DownloadError;

                await RefreshFileList();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"连接失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private async void BtnRefresh_Click(object? sender, EventArgs e)
        {
            try
            {
                await RefreshFileList();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"刷新列表失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private async Task RefreshFileList()
        {
            if (downloadService == null)
            {
                throw new Exception("下载服务未初始化");
            }
            listViewFiles.Items.Clear();
            fileList = await downloadService.GetFileListAsync();

            foreach (var file in fileList)
            {
                ListViewItem item = new ListViewItem(file.Name);
                item.SubItems.Add(FormatFileSize(file.Size));
                item.SubItems.Add(file.LastModified.ToString("yyyy-MM-dd HH:mm:ss"));
                item.SubItems.Add("可下载");
                item.Tag = file;
                listViewFiles.Items.Add(item);
            }
        }

        private void BtnDownload_Click(object? sender, EventArgs e)
        {
            if (listViewFiles.SelectedItems.Count == 0)
            {
                MessageBox.Show("请选择要下载的文件", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            foreach (ListViewItem item in listViewFiles.SelectedItems)
            {
                if (item.Tag is FileData fileData)
                {
                    _ = StartDownload(fileData); // 并行启动
                }
            }
        }

        private async Task StartDownload(FileData fileData)
        {
            if (downloadService == null) return;

            // 检查是否已在下载
            if (downloadTasks.ContainsKey(fileData.Name))
            {
                MessageBox.Show($"文件 {fileData.Name} 正在下载中", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            var downloadTask = new DownloadTask
            {
                FileName = fileData.Name,
                TotalSize = fileData.Size,
                Status = StatusDownloading,
                TokenSource = new CancellationTokenSource()
            };

            downloadTasks[fileData.Name] = downloadTask;

            // 添加到下载列表
            ListViewItem listItem = new ListViewItem(fileData.Name);
            listItem.SubItems.Add("0%");
            listItem.SubItems.Add("0 KB/s");
            listItem.SubItems.Add("计算中...");
            listItem.SubItems.Add(StatusDownloading);
            listItem.Tag = downloadTask;
            listViewDownloads.Items.Add(listItem);

            btnPauseResume.Text = PauseText;
            UpdateDownloadButtonsEnabled();

            try
            {
                await downloadService.DownloadFileAsync(fileData.Name, downloadTask.TokenSource.Token);
            }
            catch (OperationCanceledException)
            {
                downloadTask.Status = StatusPaused;
                UpdateDownloadListItem(listItem, downloadTask);
                btnPauseResume.Text = ResumeText;
            }
            catch (Exception ex)
            {
                downloadTask.Status = "下载失败";
                UpdateDownloadListItem(listItem, downloadTask);
                MessageBox.Show($"下载文件 {fileData.Name} 失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                btnPauseResume.Text = PauseText;
                btnPauseResume.Enabled = false;
            }
        }

        private async Task ContinueDownload(DownloadTask downloadTask)
        {
            if (downloadService == null || downloadTask == null)
                return;

            btnPauseResume.Enabled = true;
            btnPauseResume.Text = PauseText;

            try
            {
                await downloadService.DownloadFileAsync(downloadTask.FileName, downloadTask.TokenSource.Token);
            }
            catch (OperationCanceledException)
            {
                downloadTask.Status = StatusPaused;
                foreach (ListViewItem item in listViewDownloads.Items)
                {
                    if (item.Tag is DownloadTask task && task.FileName == downloadTask.FileName)
                    {
                        UpdateDownloadListItem(item, downloadTask);
                        break;
                    }
                }
                btnPauseResume.Text = ResumeText;
            }
            catch (Exception ex)
            {
                downloadTask.Status = "下载失败";
                foreach (ListViewItem item in listViewDownloads.Items)
                {
                    if (item.Tag is DownloadTask task && task.FileName == downloadTask.FileName)
                    {
                        UpdateDownloadListItem(item, downloadTask);
                        break;
                    }
                }
                MessageBox.Show($"下载文件 {downloadTask.FileName} 失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                btnPauseResume.Text = PauseText;
                btnPauseResume.Enabled = false;
            }
        }

        private void DownloadService_DownloadProgressChanged(object? sender, ProgressEventArgs e)
        {
            if (InvokeRequired)
            {
                Invoke(new Action(() => DownloadService_DownloadProgressChanged(sender, e)));
                return;
            }

            string fileName = e.FileName;
            if (downloadTasks.TryGetValue(fileName, out var downloadTask))
            {
                downloadTask.BytesReceived = e.BytesReceived;
                downloadTask.DownloadSpeed = e.DownloadSpeed;
                downloadTask.EstimatedTimeRemaining = e.EstimatedTimeRemaining;

                // 更新列表项
                foreach (ListViewItem item in listViewDownloads.Items)
                {
                    if (item.Tag is DownloadTask task && task.FileName == fileName)
                    {
                        UpdateDownloadListItem(item, downloadTask);
                        break;
                    }
                }
                // 按状态联动按钮
                if (downloadTask.Status == StatusDownloading)
                {
                    btnPauseResume.Text = PauseText;
                }
                else if (downloadTask.Status == StatusPaused)
                {
                    btnPauseResume.Text = ResumeText;
                }
            }
        }

        private void DownloadService_DownloadCompleted(object? sender, string filePath)
        {
            if (InvokeRequired)
            {
                Invoke(new Action(() => DownloadService_DownloadCompleted(sender, filePath)));
                return;
            }

            var fileName = Path.GetFileName(filePath);
            if (downloadTasks.TryGetValue(fileName, out var downloadTask))
            {
                downloadTask.Status = "已完成";
                downloadTask.BytesReceived = downloadTask.TotalSize;

                // 更新列表项
                foreach (ListViewItem item in listViewDownloads.Items)
                {
                    if (item.Tag is DownloadTask task && task.FileName == fileName)
                    {
                        UpdateDownloadListItem(item, downloadTask);
                        break;
                    }
                }
                downloadTasks.Remove(fileName);
                MessageBox.Show($"文件 {fileName} 下载完成！\n保存位置: {filePath}", "下载完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            btnPauseResume.Text = PauseText;
            UpdateDownloadButtonsEnabled();
        }

        private void DownloadService_DownloadError(object? sender, string error)
        {
            if (InvokeRequired)
            {
                Invoke(new Action(() => DownloadService_DownloadError(sender, error)));
                return;
            }

            MessageBox.Show($"下载错误: {error}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            btnPauseResume.Text = PauseText;
            UpdateDownloadButtonsEnabled();
        }

        private void UpdateDownloadListItem(ListViewItem item, DownloadTask task)
        {
            if (item.SubItems.Count >= 5)
            {
                var progress = task.TotalSize > 0 ? (double)task.BytesReceived / task.TotalSize * 100 : 0;
                item.SubItems[1].Text = $"{progress:F1}%";
                item.SubItems[2].Text = FormatFileSize(task.DownloadSpeed) + "/s";
                item.SubItems[3].Text = FormatTimeSpan(task.EstimatedTimeRemaining);
                item.SubItems[4].Text = task.Status;
            }
        }

        private void BtnPauseResume_Click(object? sender, EventArgs e)
        {
            if (listViewDownloads.SelectedItems.Count == 0)
            {
                MessageBox.Show("请选择要操作的下载任务", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            foreach (ListViewItem item in listViewDownloads.SelectedItems)
            {
                if (item.Tag is DownloadTask task)
                {
                    if (task.Status == StatusDownloading)
                    {
                        // 暂停下载
                        task.TokenSource?.Cancel();
                        task.Status = StatusPaused;
                        UpdateDownloadListItem(item, task);
                        btnPauseResume.Text = ResumeText;
                    }
                    else if (task.Status == StatusPaused)
                    {
                        // 继续下载
                        task.TokenSource = new CancellationTokenSource();
                        _ = ContinueDownload(task);
                        task.Status = StatusDownloading;
                        UpdateDownloadListItem(item, task);
                        btnPauseResume.Text = PauseText;
                    }
                }
            }
        }

        private void BtnCancel_Click(object? sender, EventArgs e)
        {
            if (listViewDownloads.SelectedItems.Count == 0)
            {
                MessageBox.Show("请选择要取消的下载任务", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            foreach (ListViewItem item in listViewDownloads.SelectedItems.Cast<ListViewItem>().ToList())
            {
                if (item.Tag is DownloadTask task)
                {
                    task.TokenSource?.Cancel();
                    task.Status = "已取消";
                    // 主线程安全地移除项
                    if (InvokeRequired)
                    {
                        Invoke(new Action(() => listViewDownloads.Items.Remove(item)));
                    }
                    else
                    {
                        listViewDownloads.Items.Remove(item);
                    }
                    downloadTasks.Remove(task.FileName);
                    downloadService?.CancelDownload(task.FileName);
                }
            }
            UpdateDownloadButtonsEnabled();
        }


        private string FormatFileSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB", "TB" };
            double len = bytes;
            int order = 0;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len = len / 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }

        private string FormatTimeSpan(TimeSpan timeSpan)
        {
            if (timeSpan.TotalHours >= 1)
            {
                return $"{(int)timeSpan.TotalHours}h {timeSpan.Minutes}m";
            }
            else if (timeSpan.TotalMinutes >= 1)
            {
                return $"{(int)timeSpan.TotalMinutes}m {timeSpan.Seconds}s";
            }
            else
            {
                return $"{timeSpan.Seconds}s";
            }
        }
    }
}
